package com.wuercloud.config;

import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitManagementTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.retry.backoff.BackOffPolicy;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.web.client.RestTemplate;

import com.wuercloud.swagger.WawaRabbitClient;

import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Configuration
@ComponentScan("com.wuercloud")
@PropertySource(value = "classpath:mq/rabbitmq-conf.properties", ignoreResourceNotFound = true)
public class RabbitmqConfiguration {
	@Autowired
	private Environment environment;

	@Bean("restClientTemplate")
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}

	
	@Bean("wawaRabbitClient")
	public WawaRabbitClient wawaRabbitClient() throws MalformedURLException, URISyntaxException {
		WawaRabbitClient wawaRabbitClient = new WawaRabbitClient(
				environment.getProperty("rabbitmq-manage-url"),
				environment.getProperty("rabbitmq-Username"),
				environment.getProperty("rabbitmq-Password"));
		return wawaRabbitClient;
	}
	/*
	 * @Bean public FastJsonMessageConverter fastJsonMessageConverter(){ return
	 * new FastJsonMessageConverter(); }
	 */

	/**
	 * rabbitmq管理器，可以对队列进行管理，调用其rest
	 * 
	 * @return
	 */
	@Bean
	public RabbitManagementTemplate rabbitManagementTemplate() {
		RabbitManagementTemplate rabbitManagementTemplate = new RabbitManagementTemplate(
				environment.getProperty("rabbitmq-manage-url"), 
				environment.getProperty("rabbitmq-Username"),
				environment.getProperty("rabbitmq-Password"));
		return rabbitManagementTemplate;
	}

	@Bean("rabbitConnectionFactory")
	public ConnectionFactory rabbitConnectionFactory() {
		CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
		connectionFactory.setAddresses(environment.getProperty("rabbitmq-Address"));
		connectionFactory.setVirtualHost(environment.getProperty("rabbitmq-VirtualHost"));
		connectionFactory.setUsername(environment.getProperty("rabbitmq-Username"));
		connectionFactory.setPassword(environment.getProperty("rabbitmq-Password"));
		// 设置为手工确认模式
		connectionFactory.setPublisherConfirms(true);
		connectionFactory.setPublisherReturns(true);
		ExecutorService service = Executors
				.newFixedThreadPool(Integer.parseInt(environment.getProperty("rabbitmq-fixThreadNums")));
		connectionFactory.setExecutor(service);
		connectionFactory.setConnectionTimeout(30000);
		// connectionFactory.setChannelCacheSize(Runtime.getRuntime().availableProcessors());
		connectionFactory.setChannelCacheSize(Integer.parseInt(environment.getProperty("rabbitmq-ChannelCacheSize")));
		// 线程池
		connectionFactory.setConnectionThreadFactory(
				new CustomizableThreadFactory(environment.getProperty("rabbitmq-ThreadNamePrefix")));
		return connectionFactory;
	}

	@Bean
	public RabbitAdmin rabbitAdmin() {
		return new RabbitAdmin(rabbitConnectionFactory());
	}

	/**
	 * 失败重试发送模板，其他template需用时要注入此bean
	 * 如：template.setRetryTemplate(retryTemplate);
	 * retryTemplate需要在业务类中@Autowired
	 * 
	 * @return
	 */
	@Bean
	public RetryTemplate retryTemplate() {
		RetryTemplate retryTemplate = new RetryTemplate() {
			@Override
			public void setBackOffPolicy(BackOffPolicy backOffPolicy) {
				ExponentialBackOffPolicy policy = new ExponentialBackOffPolicy();
				/*
				 * 失败重试机制，发送失败之后，会尝试重发三次，重发间隔(ms)为 第一次 initialInterval
				 * 此后：initialInterval*multiplier > maxInterval ? maxInterval :
				 * initialInterval*multiplier。
				 * 配合集群使用的时候，当mq集群中一个down掉之后，重试机制尝试其他可用的mq。 API默认为： private
				 * volatile long initialInterval = 100L; private volatile long
				 * maxInterval = 30000L; private volatile double multiplier =
				 * 2.0D;
				 */
				policy.setInitialInterval(Integer
						.parseInt(environment
						.getProperty("backOffPolicy.initialInterval")));
				policy.setMultiplier(Integer
						.parseInt(environment
						.getProperty("backOffPolicy.multiplier")));
				policy.setMaxInterval(Integer
						.parseInt(environment
						.getProperty("backOffPolicy.maxInterval")));

			}
		};
		return retryTemplate;
	}

}
